﻿using Apewer.Internals;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;

namespace Apewer
{

    /// <summary>数值实用工具。</summary>
    public static class NumberUtility
    {

        #region 随机数。

        /// <summary>用于生成随机数的时钟位置。</summary>
        private static int RandomSeed = Guid.NewGuid().ToString().GetHashCode();

        private static void RandomInit()
        {
            var now = DateTime.Now;
            var timer = (float)((double)(checked((60 * now.Hour + now.Minute) * 60 + now.Second)) + (double)now.Millisecond / 1000.0);
            int num1 = RandomSeed;
            int num2 = BitConverter.ToInt32(BitConverter.GetBytes(timer), 0);
            num2 = ((num2 & 65535) ^ num2 >> 16) << 8;
            num1 = (num1 & -16776961) | num2;
            RandomSeed = num1;
        }

        /// <summary>生成不大于 1 的随机数，最小为 0。</summary>
        public static float Random(float max = 1F)
        {
            RandomInit();
            int num1 = RandomSeed;
            if ((double)max != 0.0)
            {
                if ((double)max < 0.0)
                {
                    num1 = BitConverter.ToInt32(BitConverter.GetBytes(max), 0);
                    long vnum2 = (long)num1;
                    vnum2 &= unchecked((long)((ulong)-1));
                    num1 = checked((int)(vnum2 + (vnum2 >> 24) & 16777215L));
                }
                num1 = checked((int)(unchecked((long)num1) * 1140671485L + 12820163L & 16777215L));
            }
            RandomSeed = num1;
            return (float)num1 / 16777216f;
        }

        /// <summary>生成随机整数，包含最小值和最大值。</summary>
        /// <param name="min">最小值。</param>
        /// <param name="max">最大值。</param>
        /// <returns></returns>
        public static int Random(int max, int min = 0)
        {
            if (max == min) return max;
            if (max < min)
            {
                var temp = max;
                max = min;
                min = temp;
            }
            var rate = (max - min + 1) * Random();
            var result = min + (int)rate;
            return result;
        }

        /// <summary>对数组填充随机数。<br />0 &lt;= value &lt; 1.0</summary>
        public static void Random(float[] array, int offset = 0, int count = -1)
        {
            if (array == null) return;
            if (count == 0) return;
            var length = array.LongLength;
            var end = length;
            if (count > 0) end = offset + count;
            if (end > length) end = length;

            RandomInit();
            var max = 1.0;
            for (var i = offset; i < end; i++)
            {
                if (i < 0) continue;

                int num1 = RandomSeed;
                if ((double)max != 0.0)
                {
                    if ((double)max < 0.0)
                    {
                        num1 = BitConverter.ToInt32(BitConverter.GetBytes(max), 0);
                        long vnum2 = (long)num1;
                        vnum2 &= unchecked((long)((ulong)-1));
                        num1 = checked((int)(vnum2 + (vnum2 >> 24) & 16777215L));
                    }
                    num1 = checked((int)(unchecked((long)num1) * 1140671485L + 12820163L & 16777215L));
                }
                RandomSeed = num1;
                array[i] = (float)num1 / 16777216f;
            }
        }

        /// <summary>对数组填充随机数。<br />0 &lt;= value &lt;= 255</summary>
        public static void Random(byte[] array, int offset = 0, int count = -1) { }

        static ulong UuidGetSystemTime(DateTime dt)
        {
            /* UUID system time starts at October 15, 1582 */
            // const long TICKS_PER_CLOCK_TICK = 1000L;
            const long SECSPERDAY = 86400L;
            const long TICKSPERSEC = 10000000L;
            const long SECS_15_OCT_1582_TO_1601 = (17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY;
            const long TICKS_15_OCT_1582_TO_1601 = SECS_15_OCT_1582_TO_1601 * TICKSPERSEC;

            var ticks = dt.Ticks;
            ticks += (17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY;
            ticks += TICKS_15_OCT_1582_TO_1601;

            return default;
        }

        /// <summary>生成 GUID。</summary>
        static byte[] NewGuid()
        {
            // DWORD Data1 // 随机数
            // WORD Data2 // 和时间相关
            // WORD Data3 // 和时间相关
            // BYTE Data4[8] // 和网卡 MAC 相关

            var guid = new byte[16];

            // 全部生成随机数。
            for (var i = 0; i < 16; i++) guid[i] = Convert.ToByte(NumberUtility.Random(255, 0));

            guid[6] &= 0x0f;
            guid[6] |= 0x04;
            guid[7] &= 0xff;
            guid[7] |= 0x00;
            guid[8] &= 0x3f;
            guid[8] |= 0x80;
            return guid;
        }

        #endregion

        #region Restrict 约束值范围。

        /// <summary>约束值范围，若源值不在范围中，则修改为接近的值。</summary>
        public static T Restrict<T>(T origin, T min, T max) where T : IComparable
        {
            try
            {
                // 检查条件 min > max : 返回原始值。
                var condition = min.CompareTo(max);
                if (condition > 0) return origin;

                if (origin.CompareTo(min) < 0) return min;
                if (origin.CompareTo(max) > 0) return max;
                return origin;
            }
            catch { }

            return origin;
        }

        #endregion

        #region 表达式计算

        /// <summary>计算文本表达式，以 Int64 输出结果。</summary>
        public static long ComputeInt64(this string expression)
        {
            var result = Source.SourceUtility.Compute(expression);
            if (result == null) return 0L;
            if (result is long @long) return @long;
            return Int64(result);
        }

        /// <summary>计算文本表达式，以 Double 输出结果。</summary>
        public static double ComputeDouble(this string expression)
        {
            var result = Source.SourceUtility.Compute(expression);
            if (result == null) return 0D;
            if (result is double @double) return @double;
            return Double(result);
        }

        #endregion

        #region 平均值

        /// <summary>平均值。</summary>
        public static float Average(params float[] values)
        {
            if (values == null) return 0F;

            var amount = 0F;
            foreach (var i in values) amount += i;
            return amount / values.Length;
        }

        /// <summary>平均值。</summary>
        public static double Average(params double[] values)
        {
            if (values == null) return 0D;

            var amount = 0D;
            foreach (var i in values) amount += i;
            return amount / Convert.ToDouble(values.Length);
        }

        /// <summary>平均值。</summary>
        public static decimal Average(params decimal[] values)
        {
            if (values == null) return 0M;

            var amount = 0M;
            foreach (var i in values) amount += i;
            return amount / Convert.ToDecimal(values.Length);
        }

        #endregion

        #region 标准差

        /// <summary>计算标准差。</summary>
        /// <param name="values">值。</param>
        /// <param name="sample">计算样本标准差，分母为 n - 1。此值为 false 时计算总体标准差。</param>
        public static double Stdev(this IEnumerable<double> values, bool sample = false)
        {
            if (values == null) return 0;

            var count = 0;
            var sum = 0D;
            var up = 0D;
            if (values is double[] array)
            {
                count = array.Length;
                if (count < 1) return 0;
                for (var i = 0; i < count; i++) sum += array[i];

                var avg = sum / count;
                for (var i = 0; i < count; i++) up += (array[i] - avg) * (array[i] - avg);
            }
            else if (values is IList<double> list)
            {
                count = list.Count;
                if (count < 1) return 0;
                for (var i = 0; i < count; i++) sum += list[i];

                var avg = sum / count;
                for (var i = 0; i < count; i++) up += (list[i] - avg) * (list[i] - avg);
            }
            else
            {
                foreach (var value in values)
                {
                    sum += value;
                    count++;
                }
                if (count < 1) return 0;

                var avg = sum / count;
                foreach (var value in values)
                {
                    up += (value - avg) * (value - avg);
                    count++;
                }
            }

            // 样本标准差，最少要 2 个值。
            if (sample)
            {
                var down = count - 1;
                if (down == 0) return 0;

                var sigma = Math.Sqrt(up / down);
                return sigma;
            }
            else
            {
                var sigma = Math.Sqrt(up / count);
                return sigma;
            }
        }

        /// <summary>计算总体标准差，分母为 n。</summary>
        /// <param name="values">值。</param>
        public static double StdevP(this IEnumerable<double> values) => Stdev(values, false);

        /// <summary>计算样本标准差，分母为 n - 1。</summary>
        /// <param name="values">值。</param>
        public static double StdevS(this IEnumerable<double> values) => Stdev(values, true);

        /// <summary>计算标准差。</summary>
        /// <param name="values">值。</param>
        /// <param name="sample">计算样本标准差，分母为 n - 1。此值为 false 时计算总体标准差。</param>
        public static float Stdev(this IEnumerable<float> values, bool sample = false)
        {
            if (values == null) return 0;

            var count = 0;
            var sum = 0F;
            var up = 0F;
            if (values is float[] array)
            {
                count = array.Length;
                if (count < 1) return 0;
                for (var i = 0; i < count; i++) sum += array[i];

                var avg = sum / count;
                for (var i = 0; i < count; i++) up += (array[i] - avg) * (array[i] - avg);
            }
            else if (values is IList<float> list)
            {
                count = list.Count;
                if (count < 1) return 0;
                for (var i = 0; i < count; i++) sum += list[i];

                var avg = sum / count;
                for (var i = 0; i < count; i++) up += (list[i] - avg) * (list[i] - avg);
            }
            else
            {
                foreach (var value in values)
                {
                    sum += value;
                    count++;
                }
                if (count < 1) return 0;

                var avg = sum / count;
                foreach (var value in values)
                {
                    up += (value - avg) * (value - avg);
                    count++;
                }
            }

            // 样本标准差，最少要 2 个值。
            if (sample)
            {
                var down = count - 1;
                if (down == 0) return 0;

                var sigma = Convert.ToSingle(Math.Sqrt(up / down));
                return sigma;
            }
            else
            {
                var sigma = Convert.ToSingle(Math.Sqrt(up / count));
                return sigma;
            }
        }

        /// <summary>计算总体标准差，分母为 n。</summary>
        /// <param name="values">值。</param>
        public static float StdevP(this IEnumerable<float> values) => Stdev(values, false);

        /// <summary>计算样本标准差，分母为 n - 1。</summary>
        /// <param name="values">值。</param>
        public static float StdevS(this IEnumerable<float> values) => Stdev(values, true);

        /// <summary>计算标准差。</summary>
        /// <param name="values">值。</param>
        /// <param name="sample">计算样本标准差，分母为 n - 1。此值为 false 时计算总体标准差。</param>
        public static decimal Stdev(this IEnumerable<decimal> values, bool sample = false)
        {
            if (values == null) return 0;

            var count = 0;
            var sum = 0M;
            var up = 0M;
            if (values is decimal[] array)
            {
                count = array.Length;
                if (count < 1) return 0;
                for (var i = 0; i < count; i++) sum += array[i];

                var avg = sum / count;
                for (var i = 0; i < count; i++) up += (array[i] - avg) * (array[i] - avg);
            }
            else if (values is IList<decimal> list)
            {
                count = list.Count;
                if (count < 1) return 0;
                for (var i = 0; i < count; i++) sum += list[i];

                var avg = sum / count;
                for (var i = 0; i < count; i++) up += (list[i] - avg) * (list[i] - avg);
            }
            else
            {
                foreach (var value in values)
                {
                    sum += value;
                    count++;
                }
                if (count < 1) return 0;

                var avg = sum / count;
                foreach (var value in values)
                {
                    up += (value - avg) * (value - avg);
                    count++;
                }
            }

            // 样本标准差，最少要 2 个值。
            if (sample)
            {
                var down = count - 1;
                if (down == 0) return 0;

                var sigma = Convert.ToDecimal(Math.Sqrt(Convert.ToDouble(up / down)));
                return sigma;
            }
            else
            {
                var sigma = Convert.ToDecimal(Math.Sqrt(Convert.ToDouble(up / count)));
                return sigma;
            }
        }

        /// <summary>计算总体标准差，分母为 n。</summary>
        /// <param name="values">值。</param>
        public static decimal StdevP(this IEnumerable<decimal> values) => Stdev(values, false);

        /// <summary>计算样本标准差，分母为 n - 1。</summary>
        /// <param name="values">值。</param>
        public static decimal StdevS(this IEnumerable<decimal> values) => Stdev(values, true);

        #endregion

        #region 最小值、最大值、极差

        private static T Most<T>(Func<T, T, bool> replace, T[] values)
        {
            if (values == null) return default;

            var length = values.LongLength;
            if (length == 0L) return default;
            if (length == 1L) return values[0L];

            var most = values[0];
            for (var i = 1L; i < length; i++)
            {
                var value = values[i];
                if (value == null) continue;
                if (most == null)
                {
                    most = value;
                }
                else
                {
                    var doReplace = replace(most, value);
                    if (doReplace) most = value;
                }
            }
            return most;
        }

        /// <summary>最小值。</summary>
        public static byte Min(params byte[] values) => Most((a, b) => a > b, values);

        /// <summary>最小值。</summary>
        public static int Min(params int[] values) => Most((a, b) => a > b, values);

        /// <summary>最小值。</summary>
        public static long Min(params long[] values) => Most((a, b) => a > b, values);

        /// <summary>最小值。</summary>
        public static float Min(params float[] values) => Most((a, b) => a > b, values);

        /// <summary>最小值。</summary>
        public static double Min(params double[] values) => Most((a, b) => a > b, values);

        /// <summary>最小值。</summary>
        public static decimal Min(params decimal[] values) => Most((a, b) => a > b, values);

        /// <summary>最大值。</summary>
        public static byte Max(params byte[] values) => Most((a, b) => a < b, values);

        /// <summary>最大值。</summary>
        public static int Max(params int[] values) => Most((a, b) => a < b, values);

        /// <summary>最大值。</summary>
        public static long Max(params long[] values) => Most((a, b) => a < b, values);

        /// <summary>最大值。</summary>
        public static float Max(params float[] values) => Most((a, b) => a < b, values);

        /// <summary>最大值。</summary>
        public static double Max(params double[] values) => Most((a, b) => a < b, values);

        /// <summary>最大值。</summary>
        public static decimal Max(params decimal[] values) => Most((a, b) => a < b, values);

        /// <summary>极差。</summary>
        public static int Range(params int[] values) => Max(values) - Min(values);

        /// <summary>极差。</summary>
        public static long Range(params long[] values) => Max(values) - Min(values);

        /// <summary>极差。</summary>
        public static float Range(params float[] values) => Max(values) - Min(values);

        /// <summary>极差。</summary>
        public static double Range(params double[] values) => Max(values) - Min(values);

        /// <summary>极差。</summary>
        public static decimal Range(params decimal[] values) => Max(values) - Min(values);

        #endregion

        /// <summary>Pearson Correlation Coefficient 皮尔逊相关系数。计算两个数组的相似度。数组长度不相等时，以 0 填充不足的长度。</summary>
        /// <remarks>
        /// <para>0.8 ~ 1.0 : 极强相关</para>
        /// <para>0.6 ~ 0.8 : 强相关</para>
        /// <para>0.4 ~ 0.6 : 中等程度相关</para>
        /// <para>0.2 ~ 0.4 : 弱相关</para>
        /// <para>0.0 ~ 0.2 : 极弱相关或无相关</para>
        /// </remarks>
        /// <exception cref="ArgumentException"></exception>
        public static double Pearson(double[] bytes1, double[] bytes2)
        {
            var length1 = bytes1 == null ? 0L : bytes1.LongLength;
            var length2 = bytes2 == null ? 0L : bytes2.LongLength;
            var length = Math.Max(length1, length2);
            if (length < 1) return 1D;

            var x = new double[length];
            var y = new double[length];
            for (var i = 0L; i < length; i++)
            {
                if (i < length1) x[i] = bytes1[i];
                if (i < length2) y[i] = bytes2[i];
            }

            int n = x.Length; // 数组长度。
            double s = 0d; // 分子。
            double m1 = 0d, m2 = 0d; // 分母。

            double xa = Average(x);
            double ya = Average(y);
            for (int i = 0; i < n; i++)
            {
                s += (x[i] - xa) * (y[i] - ya);
                m1 += Math.Pow(x[i] - xa, 2);
                m2 += Math.Pow(y[i] - ya, 2);
            }

            double r = s / (Math.Sqrt(m1) * Math.Sqrt(m2));
            return r;
        }

        #region 从 String 转为数值。

        // 修剪数值字符串。
        private static string Trim(string text)
        {
            if (string.IsNullOrEmpty(text)) return null;
            const string allowed = "0123456789.%+-Ee。";
            var input = text.Length;
            var output = 0;
            var chars = new char[input];
            for (var i = 0; i < text.Length; i++)
            {
                var c = text[i];
                if (c == '。') c = '.';
                else if (allowed.IndexOf(c) < 0) continue;
                chars[output] = c;
                output += 1;
            }
            if (output == input) return text;
            if (output < 1) return null;
            return new string(chars, 0, output);
        }

        private static T GetNumber<T>(object @object, Func<string, T> convert, Func<T, double, T> percent = null)
        {
            if (@object == null) return default(T);
            if (@object is T) return (T)@object;
            var text = (@object is string) ? (string)@object : @object.ToString();
            var trim = Trim(text);
            if (trim == null) return default;

            // 获取百分号的个数。
            var pow = 0;
            while (trim.Length > 0 && trim.EndsWith("%"))
            {
                trim = trim.Substring(0, trim.Length - 1);
                pow += 1;
            }
            if (trim.Length < 1) return default;

            // 转换。
            try
            {
                var value = convert(trim);
                if (pow > 0 && percent != null)
                {
                    var denominator = Math.Pow(100, pow);
                    value = percent(value, denominator);
                }
                return value;
            }
            catch { return default; }
        }

        private static decimal DecimalAsFloat(string text)
        {
            try { return Convert.ToDecimal(text); } catch { }
            try { return decimal.Parse(text, NumberStyles.Float); } catch { }
            return default(decimal);
        }

        /// <summary>获取布尔对象。</summary>
        public static bool Boolean(object any)
        {
            if (any.IsNull()) return false;
            if (any is bool _bool) return _bool;
            if (any is byte _byte) return _byte == 1;
            if (any is sbyte _sbyte) return _sbyte == 1;
            if (any is short _short) return _short == 1;
            if (any is ushort _ushort) return _ushort == 1;
            if (any is int _int) return _int == 1;
            if (any is uint _uint) return _uint == 1;
            if (any is long _long) return _long == 1;
            if (any is ulong _ulong) return _ulong == 1;
            if (any is float _float) return _float == 1;
            if (any is double _double) return _double == 1;
            if (any is decimal _decimal) return _decimal == 1;
            if (any is string _string)
            {
                var lower = TextUtility.Lower(_string);
                if (lower == "true" || lower == "yes" || lower == "y" || lower == "1") return true;
            }
            return false;
        }

        private static Tout Try<Tin, Tout>(Tin value, Func<Tin, Tout> func)
        {
            try { return func.Invoke(value); }
            catch { return default(Tout); }
        }

        /// <summary>获取单精度浮点对象。</summary>
        public static float Float(object number)
        {
            if (number is bool _bool) return Try(_bool, Convert.ToSingle);
            if (number is byte _byte) return Try(_byte, Convert.ToSingle);
            if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToSingle);
            if (number is short _short) return Try(_short, Convert.ToSingle);
            if (number is ushort _ushort) return Try(_ushort, Convert.ToSingle);
            if (number is int _int) return Try(_int, Convert.ToSingle);
            if (number is uint _uint) return Try(_uint, Convert.ToSingle);
            if (number is long _long) return Try(_long, Convert.ToSingle);
            if (number is ulong _ulong) return Try(_ulong, Convert.ToSingle);
            if (number is float _float) return Try(_float, Convert.ToSingle);
            if (number is double _double) return Try(_double, Convert.ToSingle);
            if (number is decimal _decimal) return Try(_decimal, Convert.ToSingle);
            return GetNumber(number, Convert.ToSingle, (v, d) => v / Convert.ToSingle(d));
        }

        /// <summary>获取单精度浮点对象。</summary>
        public static float Single(object number)
        {
            if (number is bool _bool) return Try(_bool, Convert.ToSingle);
            if (number is byte _byte) return Try(_byte, Convert.ToSingle);
            if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToSingle);
            if (number is short _short) return Try(_short, Convert.ToSingle);
            if (number is ushort _ushort) return Try(_ushort, Convert.ToSingle);
            if (number is int _int) return Try(_int, Convert.ToSingle);
            if (number is uint _uint) return Try(_uint, Convert.ToSingle);
            if (number is long _long) return Try(_long, Convert.ToSingle);
            if (number is ulong _ulong) return Try(_ulong, Convert.ToSingle);
            if (number is float _float) return Try(_float, Convert.ToSingle);
            if (number is double _double) return Try(_double, Convert.ToSingle);
            if (number is decimal _decimal) return Try(_decimal, Convert.ToSingle);
            return GetNumber(number, Convert.ToSingle, (v, d) => v / Convert.ToSingle(d));
        }

        /// <summary>获取双精度浮点对象。</summary>
        public static double Double(object number)
        {
            if (number is bool _bool) return Try(_bool, Convert.ToDouble);
            if (number is byte _byte) return Try(_byte, Convert.ToDouble);
            if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToDouble);
            if (number is short _short) return Try(_short, Convert.ToDouble);
            if (number is ushort _ushort) return Try(_ushort, Convert.ToDouble);
            if (number is int _int) return Try(_int, Convert.ToDouble);
            if (number is uint _uint) return Try(_uint, Convert.ToDouble);
            if (number is long _long) return Try(_long, Convert.ToDouble);
            if (number is ulong _ulong) return Try(_ulong, Convert.ToDouble);
            if (number is float _float) return Try(_float, Convert.ToDouble);
            if (number is double _double) return Try(_double, Convert.ToDouble);
            if (number is decimal _decimal) return Try(_decimal, Convert.ToDouble);
            return GetNumber(number, Convert.ToDouble, (v, d) => v / d);
        }

        /// <summary>获取 Decimal 对象。</summary>
        public static decimal Decimal(object number)
        {
            if (number is bool _bool) return Try(_bool, Convert.ToDecimal);
            if (number is byte _byte) return Try(_byte, Convert.ToDecimal);
            if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToDecimal);
            if (number is short _short) return Try(_short, Convert.ToDecimal);
            if (number is ushort _ushort) return Try(_ushort, Convert.ToDecimal);
            if (number is int _int) return Try(_int, Convert.ToDecimal);
            if (number is uint _uint) return Try(_uint, Convert.ToDecimal);
            if (number is long _long) return Try(_long, Convert.ToDecimal);
            if (number is ulong _ulong) return Try(_ulong, Convert.ToDecimal);
            if (number is float _float) return Try(_float, Convert.ToDecimal);
            if (number is double _double) return Try(_double, Convert.ToDecimal);
            if (number is decimal _decimal) return Try(_decimal, Convert.ToDecimal);
            return GetNumber(number, DecimalAsFloat, (v, d) => v / Convert.ToDecimal(d));
        }

        /// <summary>获取 Byte 对象。</summary>
        public static byte Byte(object number)
        {
            if (number is bool _bool) return Try(_bool, Convert.ToByte);
            if (number is byte _byte) return Try(_byte, Convert.ToByte);
            if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToByte);
            if (number is short _short) return Try(_short, Convert.ToByte);
            if (number is ushort _ushort) return Try(_ushort, Convert.ToByte);
            if (number is int _int) return Try(_int, Convert.ToByte);
            if (number is uint _uint) return Try(_uint, Convert.ToByte);
            if (number is long _long) return Try(_long, Convert.ToByte);
            if (number is ulong _ulong) return Try(_ulong, Convert.ToByte);
            if (number is float _float) return Try(_float, Convert.ToByte);
            if (number is double _double) return Try(_double, Convert.ToByte);
            if (number is decimal _decimal) return Try(_decimal, Convert.ToByte);
            return GetNumber(number, Convert.ToByte);
        }

        /// <summary>获取 SByte 对象。</summary>
        public static sbyte SByte(object number)
        {
            if (number is bool _bool) return Try(_bool, Convert.ToSByte);
            if (number is byte _byte) return Try(_byte, Convert.ToSByte);
            if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToSByte);
            if (number is short _short) return Try(_short, Convert.ToSByte);
            if (number is ushort _ushort) return Try(_ushort, Convert.ToSByte);
            if (number is int _int) return Try(_int, Convert.ToSByte);
            if (number is uint _uint) return Try(_uint, Convert.ToSByte);
            if (number is long _long) return Try(_long, Convert.ToSByte);
            if (number is ulong _ulong) return Try(_ulong, Convert.ToSByte);
            if (number is float _float) return Try(_float, Convert.ToSByte);
            if (number is double _double) return Try(_double, Convert.ToSByte);
            if (number is decimal _decimal) return Try(_decimal, Convert.ToSByte);
            return GetNumber(number, Convert.ToSByte);
        }

        /// <summary>获取 Int16 对象。</summary>
        public static short Int16(object number)
        {
            if (number is bool _bool) return Try(_bool, Convert.ToInt16);
            if (number is byte _byte) return Try(_byte, Convert.ToInt16);
            if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToInt16);
            if (number is short _short) return Try(_short, Convert.ToInt16);
            if (number is ushort _ushort) return Try(_ushort, Convert.ToInt16);
            if (number is int _int) return Try(_int, Convert.ToInt16);
            if (number is uint _uint) return Try(_uint, Convert.ToInt16);
            if (number is long _long) return Try(_long, Convert.ToInt16);
            if (number is ulong _ulong) return Try(_ulong, Convert.ToInt16);
            if (number is float _float) return Try(_float, Convert.ToInt16);
            if (number is double _double) return Try(_double, Convert.ToInt16);
            if (number is decimal _decimal) return Try(_decimal, Convert.ToInt16);
            return GetNumber(number, Convert.ToInt16);
        }

        /// <summary>获取 UInt16 对象。</summary>
        public static ushort UInt16(object number)
        {
            if (number is bool _bool) return Try(_bool, Convert.ToUInt16);
            if (number is byte _byte) return Try(_byte, Convert.ToUInt16);
            if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToUInt16);
            if (number is short _short) return Try(_short, Convert.ToUInt16);
            if (number is ushort _ushort) return Try(_ushort, Convert.ToUInt16);
            if (number is int _int) return Try(_int, Convert.ToUInt16);
            if (number is uint _uint) return Try(_uint, Convert.ToUInt16);
            if (number is long _long) return Try(_long, Convert.ToUInt16);
            if (number is ulong _ulong) return Try(_ulong, Convert.ToUInt16);
            if (number is float _float) return Try(_float, Convert.ToUInt16);
            if (number is double _double) return Try(_double, Convert.ToUInt16);
            if (number is decimal _decimal) return Try(_decimal, Convert.ToUInt16);
            return GetNumber(number, Convert.ToUInt16);
        }

        /// <summary>获取 Int32 对象。</summary>
        public static int Int32(object number)
        {
            if (number is bool _bool) return Try(_bool, Convert.ToInt32);
            if (number is byte _byte) return Try(_byte, Convert.ToInt32);
            if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToInt32);
            if (number is short _short) return Try(_short, Convert.ToInt32);
            if (number is ushort _ushort) return Try(_ushort, Convert.ToInt32);
            if (number is int _int) return Try(_int, Convert.ToInt32);
            if (number is uint _uint) return Try(_uint, Convert.ToInt32);
            if (number is long _long) return Try(_long, Convert.ToInt32);
            if (number is ulong _ulong) return Try(_ulong, Convert.ToInt32);
            if (number is float _float) return Try(_float, Convert.ToInt32);
            if (number is double _double) return Try(_double, Convert.ToInt32);
            if (number is decimal _decimal) return Try(_decimal, Convert.ToInt32);
            return GetNumber(number, Convert.ToInt32);
        }

        /// <summary>获取 UInt32 对象。</summary>
        public static uint UInt32(object number)
        {
            if (number is bool _bool) return Try(_bool, Convert.ToUInt32);
            if (number is byte _byte) return Try(_byte, Convert.ToUInt32);
            if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToUInt32);
            if (number is short _short) return Try(_short, Convert.ToUInt32);
            if (number is ushort _ushort) return Try(_ushort, Convert.ToUInt32);
            if (number is int _int) return Try(_int, Convert.ToUInt32);
            if (number is uint _uint) return Try(_uint, Convert.ToUInt32);
            if (number is long _long) return Try(_long, Convert.ToUInt32);
            if (number is ulong _ulong) return Try(_ulong, Convert.ToUInt32);
            if (number is float _float) return Try(_float, Convert.ToUInt32);
            if (number is double _double) return Try(_double, Convert.ToUInt32);
            if (number is decimal _decimal) return Try(_decimal, Convert.ToUInt32);
            return GetNumber(number, Convert.ToUInt32);
        }

        /// <summary>获取 Int64 对象。</summary>
        public static long Int64(object number)
        {
            if (number is bool _bool) return Try(_bool, Convert.ToInt64);
            if (number is byte _byte) return Try(_byte, Convert.ToInt64);
            if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToInt64);
            if (number is short _short) return Try(_short, Convert.ToInt64);
            if (number is ushort _ushort) return Try(_ushort, Convert.ToInt64);
            if (number is int _int) return Try(_int, Convert.ToInt64);
            if (number is uint _uint) return Try(_uint, Convert.ToInt64);
            if (number is long _long) return Try(_long, Convert.ToInt64);
            if (number is ulong _ulong) return Try(_ulong, Convert.ToInt64);
            if (number is float _float) return Try(_float, Convert.ToInt64);
            if (number is double _double) return Try(_double, Convert.ToInt64);
            if (number is decimal _decimal) return Try(_decimal, Convert.ToInt64);
            return GetNumber(number, Convert.ToInt64);
        }

        /// <summary>获取 UInt64 对象。</summary>
        public static ulong UInt64(object number)
        {
            if (number is bool _bool) return Try(_bool, Convert.ToUInt64);
            if (number is byte _byte) return Try(_byte, Convert.ToUInt64);
            if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToUInt64);
            if (number is short _short) return Try(_short, Convert.ToUInt64);
            if (number is ushort _ushort) return Try(_ushort, Convert.ToUInt64);
            if (number is int _int) return Try(_int, Convert.ToUInt64);
            if (number is uint _uint) return Try(_uint, Convert.ToUInt64);
            if (number is long _long) return Try(_long, Convert.ToUInt64);
            if (number is ulong _ulong) return Try(_ulong, Convert.ToUInt64);
            if (number is float _float) return Try(_float, Convert.ToUInt64);
            if (number is double _double) return Try(_double, Convert.ToUInt64);
            if (number is decimal _decimal) return Try(_decimal, Convert.ToUInt64);
            return GetNumber(number, Convert.ToUInt64);
        }

        #endregion

        #region 转为字符串

        /// <summary>转为大写中文金额。</summary>
        public static string ToChinesePrice(decimal value)
        {
            if (value == 0M) return "零圆整";
            var s = value.ToString("#L#E#D#C#K#E#D#C#J#E#D#C#I#E#D#C#H#E#D#C#G#E#D#C#F#E#D#C#.0B0A");
            var d = Regex.Replace(s, @"((?<=-|^)[^1-9]*)|((?'z'0)[0A-E]*((?=[1-9])|(?'-z'(?=[F-L\.]|$))))|((?'b'[F-L])(?'z'0)[0A-L]*((?=[1-9])|(?'-z'(?=[\.]|$))))", "${b}${z}");
            var r = Regex.Replace(d, ".", m => "负元空零壹贰叁肆伍陆柒捌玖空空空空空空空分角拾佰仟万亿兆京垓秭穰"[m.Value[0] - '-'].ToString());
            if (!(r.Contains("分") || r.Contains("角"))) r = r + "整";
            if (value < 0M) r = "负" + r;
            return r;
        }

        #endregion

    }

}
